package server

import (
	"encoding/json"
	"gitee.com/lintx/genshin-gacha-export-go/gacha"
	"github.com/360EntSecGroup-Skylar/excelize/v2"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"net/http"
)

type Client struct {
	conn    *websocket.Conn
	isLocal bool
	Data    map[string][]gacha.GaCha
}

type Message struct {
	Code     int         `json:"code"` //0:local,1:param
	Param    gacha.Param `json:"param"`
	SaveData bool        `json:"save_data"`
}

func (c *Client) read() {
	for {
		t, m, err := c.conn.ReadMessage()
		if t == -1 || err != nil {
			break
		}
		message := Message{}
		err = json.Unmarshal(m, &message)
		if err != nil {
			c.sendMessage(gacha.ErrorMessage(`无效请求`))
		}
		if message.Code == 0 || message.Code == 1 {
			ch := gacha.NewCh()
			if message.Code == 0 {
				if !c.isLocal {
					c.sendMessage(gacha.ErrorMessage(`错误的操作`))
					continue
				}
				go gacha.LocalLoad(gacha.CnPathName, ch)
			} else {
				go gacha.AuthLoad(message.Param, message.SaveData, ch)
			}

			go func() {
				for { //需要使用go func，且使用channel来处理信号，以免阻塞read m
					if r, ok := <-ch.Ch; ok {
						if r.Code == 0 {
							c.Data = r.Data
						}
						c.sendMessage(&r)
					} else {
						break
					}
				}
			}()
		} else if message.Code == 2 {
			if c.Data != nil {
				f := excelize.NewFile()
				//setActive := false
				style5, _ := f.NewStyle(`{"fill":{"type":"pattern","color":["#FAC858"],"pattern":1}}`)
				style4, _ := f.NewStyle(`{"fill":{"type":"pattern","color":["#9A60B4"],"pattern":1}}`)
				for k, v := range c.Data {
					_ = f.NewSheet(k)
					_ = f.SetColWidth(k, `A`, `A`, 12)
					_ = f.SetColWidth(k, `B`, `B`, 10)
					_ = f.SetColWidth(k, `E`, `E`, 20)
					_ = f.SetColWidth(k, `F`, `F`, 16)
					_ = f.SetColWidth(k, `J`, `J`, 20)
					_ = f.SetColVisible(k, `A:D`, false)
					_ = f.SetColVisible(k, `G`, false)
					_ = f.SetColVisible(k, `J`, false)
					_ = f.SetCellStr(k, cellName(1, 1), `uid`)
					_ = f.SetCellStr(k, cellName(2, 1), `gacha_type`)
					_ = f.SetCellStr(k, cellName(3, 1), `item_id`)
					_ = f.SetCellStr(k, cellName(4, 1), `count`)
					_ = f.SetCellStr(k, cellName(5, 1), `time`)
					_ = f.SetCellStr(k, cellName(6, 1), `name`)
					_ = f.SetCellStr(k, cellName(7, 1), `lang`)
					_ = f.SetCellStr(k, cellName(8, 1), `item_type`)
					_ = f.SetCellStr(k, cellName(9, 1), `rank_type`)
					_ = f.SetCellStr(k, cellName(10, 1), `id`)
					_ = f.SetCellStr(k, cellName(2, 2), `祈愿类型`)
					_ = f.SetCellStr(k, cellName(5, 2), `祈愿时间`)
					_ = f.SetCellStr(k, cellName(6, 2), `获得物品`)
					_ = f.SetCellStr(k, cellName(8, 2), `物品类型`)
					_ = f.SetCellStr(k, cellName(9, 2), `物品星级`)
					_ = f.SetCellStr(k, cellName(10, 2), `祈愿id`)
					for row, d := range v {
						_ = f.SetCellStr(k, cellName(1, row+3), d.Uid)
						_ = f.SetCellDefault(k, cellName(2, row+3), d.GachaType)
						_ = f.SetCellDefault(k, cellName(3, row+3), d.ItemId)
						_ = f.SetCellDefault(k, cellName(4, row+3), d.Count)
						_ = f.SetCellStr(k, cellName(5, row+3), d.Time)
						_ = f.SetCellStr(k, cellName(6, row+3), d.Name)
						_ = f.SetCellStr(k, cellName(7, row+3), d.Lang)
						_ = f.SetCellStr(k, cellName(8, row+3), d.ItemType)
						_ = f.SetCellDefault(k, cellName(9, row+3), d.RankType)
						_ = f.SetCellStr(k, cellName(10, row+3), d.Id)
						if d.RankType == `5` {
							_ = f.SetCellStyle(k, cellName(1, row+3), cellName(10, row+3), style5)
						} else if d.RankType == `4` {
							_ = f.SetCellStyle(k, cellName(1, row+3), cellName(10, row+3), style4)
						}
					}
				}
				f.DeleteSheet("Sheet1")

				buff, _ := f.WriteToBuffer()
				if buff != nil {
					_ = c.conn.WriteMessage(websocket.BinaryMessage, buff.Bytes())
				}
			} else {
				c.sendMessage(gacha.ErrorMessage(`必须先获取数据才能下载Excel文件`))
			}
		}
	}
	_ = c.conn.Close()
}

func cellName(col, row int) string {
	name, _ := excelize.CoordinatesToCellName(col, row)
	return name
}

func (c *Client) sendMessage(message *gacha.Message) {
	jsonMessage, _ := json.Marshal(message)
	_ = c.conn.WriteMessage(websocket.TextMessage, jsonMessage)
}

func WsHandler(c *gin.Context) {
	conn, err := (&websocket.Upgrader{
		CheckOrigin: func(r *http.Request) bool {
			//是否放行跨域请求
			return true
		},
	}).Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		http.NotFound(c.Writer, c.Request)
		//println(err.Error())
		return
	}
	//可以添加用户信息验证
	client := &Client{
		conn:    conn,
		isLocal: isLocal(c.ClientIP()),
	}
	//conn.SetCloseHandler(closeHandler)
	go client.read()
}
